home *** CD-ROM | disk | FTP | other *** search
- Path: sun.soe.clarkson.edu!cline
- From: cline@sun.soe.clarkson.edu (Marshall Cline)
- Newsgroups: comp.lang.c++
- Subject: C++ FAQ: posting #4/4
- Followup-To: comp.lang.c++
- Date: 6 Mar 1996 02:21:47 GMT
- Organization: Paradigm Shift, Inc (technology consulting)
- Sender: cline@sun.soe.clarkson.edu
- Distribution: world
- Expires: +1 month
- Message-ID: <4hisrr$hfm@library.erc.clarkson.edu>
- Reply-To: cline@parashift.com (Marshall Cline)
- NNTP-Posting-Host: sun.soe.clarkson.edu
- Summary: Please read this before posting to comp.lang.c++
- Archive-name: C++-faq/part4_4
-
- comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
- Copyright (C) 1991-96 Marshall P. Cline, Ph.D.
- Posting 4 of 4.
- Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc
-
- ==============================================================================
- SECTION 17: Linkage-to/relationship-with C
- ==============================================================================
-
- Q111: How can I call a C function "f(int,char,float)" from C++ code?
-
- Tell the C++ compiler that it is a C function:
- extern "C" void f(int,char,float);
-
- Be sure to include the full function prototype. A block of many C functions
- can be grouped via braces, as in:
-
- extern "C" {
- void* malloc(size_t);
- char* strcpy(char* dest, const char* src);
- int printf(const char* fmt, ...);
- }
-
- ==============================================================================
-
- Q112: How can I create a C++ function "f(int,char,float)" that is callable by
- my C code?
-
- The C++ compiler must know that "f(int,char,float)" is to be called by a C
- compiler using the same "extern C" construct detailed in the previous FAQ.
- Then you define the function in your C++ module:
-
- extern "C" void f(int,char,float);
-
- //...
-
- void f(int x, char y, float z)
- {
- //...
- }
-
- The "extern C" line tells the compiler that the external information sent to
- the linker should use C calling conventions and name mangling (e.g., preceded
- by a single underscore). Since name overloading isn't supported by C, you
- can't make several overloaded fns simultaneously callable by a C program.
-
- Caveats and implementation dependencies:
- * your "main()" should be compiled with your C++ compiler (for static init).
- * your C++ compiler should direct the linking process (for special libraries).
- * your C and C++ compilers may need to come from same vendor and have
- compatible versions (i.e., needs same calling convention, etc.).
-
- ==============================================================================
-
- Q113: Why's the linker giving errors for C/C++ fns being called from C++/C
- fns?
-
- See the previous two FAQs on how to use "extern "C"."
-
- ==============================================================================
-
- Q114: How can I pass an object of a C++ class to/from a C function?
-
- Here's an example:
-
- /****** C/C++ header file: Fred.h ******/
- #ifdef __cplusplus /*"__cplusplus" is #defined if/only-if compiler is C++*/
- extern "C" {
- #endif
-
- #ifdef __STDC__
- extern void c_fn(struct Fred*); /* ANSI-C prototypes */
- extern struct Fred* cplusplus_callback_fn(struct Fred*);
- #else
- extern void c_fn(); /* K&R style */
- extern struct Fred* cplusplus_callback_fn();
- #endif
-
- #ifdef __cplusplus
- }
- #endif
-
- #ifdef __cplusplus
- class Fred {
- public:
- Fred();
- void wilma(int);
- private:
- int a_;
- };
- #endif
-
- "Fred.C" would be a C++ module:
-
- #include "Fred.h"
- Fred::Fred() : a_(0) { }
- void Fred::wilma(int a) { }
-
- Fred* cplusplus_callback_fn(Fred* fred)
- {
- fred->wilma(123);
- return fred;
- }
-
- "main.C" would be a C++ module:
-
- #include "Fred.h"
-
- int main()
- {
- Fred fred;
- c_fn(&fred);
- return 0;
- }
-
- "c-fn.c" would be a C module:
-
- #include "Fred.h"
- void c_fn(struct Fred* fred)
- {
- cplusplus_callback_fn(fred);
- }
-
- Passing ptrs to C++ objects to/from C fns will FAIL if you pass and get back
- something that isn't EXACTLY the same pointer. For example, DON'T pass a base
- class ptr and receive back a derived class ptr, since your C compiler won't
- understand the pointer conversions necessary to handle multiple and/or virtual
- inheritance.
-
- ==============================================================================
-
- Q115: Can my C function access data in an object of a C++ class?
-
- Sometimes.
-
- (First read the previous FAQ on passing C++ objects to/from C functions.)
-
- You can safely access a C++ object's data from a C function if the C++ class:
- * has no virtual functions (including inherited virtual fns)
- * has all its data in the same access-level section (private/protected/public)
- * has no fully-contained subobjects with virtual fns
-
- If the C++ class has any base classes at all (or if any fully contained
- subobjects have base classes), accessing the data will TECHNICALLY be
- non-portable, since class layout under inheritance isn't imposed by the
- language. However in practice, all C++ compilers do it the same way: the base
- class object appears first (in left-to-right order in the event of multiple
- inheritance), and subobjects follow.
-
- Furthermore, if the class (or any base class) contains any virtual functions,
- you can often (but less than always) assume a "void*" appears in the object
- either at the location of the first virtual function or as the first word in
- the object. Again, this is not required by the language, but it is the way
- "everyone" does it.
-
- If the class has any virtual base classes, it is even more complicated and less
- portable. One common implementation technique is for objects to contain an
- object of the virtual base class (V) last (regardless of where "V" shows up as
- a virtual base class in the inheritance hierarchy). The rest of the object's
- parts appear in the normal order. Every derived class that has V as a virtual
- base class actually has a POINTER to the V part of the final object.
-
- ==============================================================================
-
- Q116: Why do I feel like I'm "further from the machine" in C++ as opposed to
- C?
-
- Because you are.
-
- As an OOPL, C++ allows you to model the problem domain itself, which allows you
- to program in the language of the problem domain rather than in the language of
- the solution domain.
-
- One of C's great strengths is the fact that it has "no hidden mechanism": what
- you see is what you get. You can read a C program and "see" every clock cycle.
- This is not the case in C++; old line C programmers (such as many of us once
- were) are often ambivalent (can anyone say, "hostile") about this feature, but
- they soon realize that it provides a level of abstraction and economy of
- expression which lowers maintenance costs without destroying run-time
- performance.
-
- Naturally you can write bad code in any language; C++ doesn't guarantee any
- particular level of quality, reusability, abstraction, or any other measure of
- "goodness." C++ doesn't try to make it impossible for bad programmers to write
- bad programs; it enables reasonable developers to create superior software.
-
- ==============================================================================
- SECTION 18: Pointers to member functions
- ==============================================================================
-
- Q117: Is the type of "ptr-to-member-fn" different from "ptr-to-fn"?
-
- Yep.
-
- Consider the following function:
-
- int f(char a, float b);
-
- If this is an ordinary function, its type is: int (*) (char,float);
- If this is a method of class Fred, its type is: int (Fred::*)(char,float);
-
- ==============================================================================
-
- Q118: How do I pass a ptr to member fn to a signal handler, X event callback,
- etc?
-
- Don't.
-
- Because a member function is meaningless without an object to invoke it on, you
- can't do this directly (if The X Windows System was rewritten in C++, it would
- probably pass references to OBJECTS around, not just pointers to fns; naturally
- the objects would embody the required function and probably a whole lot more).
-
- As a patch for existing software, use a top-level (non-member) function as a
- wrapper which takes an object obtained through some other technique (held in a
- global, perhaps). The top-level function would apply the desired member
- function against the global object.
-
- E.g., suppose you want to call Fred::memfn() on interrupt:
-
- class Fred {
- public:
- void memfn();
- static void staticmemfn(); //a static member fn can handle it
- //...
- };
-
- //wrapper fn remembers the object on which to invoke memfn in a global:
- Fred* object_which_will_handle_signal;
- void Fred_memfn_wrapper() { object_which_will_handle_signal->memfn(); }
-
- main()
- {
- /* signal(SIGINT, Fred::memfn); */ //Can NOT do this
- signal(SIGINT, Fred_memfn_wrapper); //Ok
- signal(SIGINT, Fred::staticmemfn); //Also Ok
- }
-
- Note: static member functions do not require an actual object to be invoked, so
- ptrs-to-static-member-fns are type compatible with regular ptrs-to-fns (see ARM
- ["Annotated Reference Manual"] p.25, 158).
-
- ==============================================================================
-
- Q119: Why do I keep getting compile errors (type mismatch) when I try to use a
- member function as an interrupt service routine?
-
- This is a special case of the previous two questions, therefore read the
- previous two answers first.
-
- Non-static member functions have a hidden parameter that corresponds to the
- 'this' pointer. The 'this' pointer points to the instance data for the
- object. The interrupt hardware/firmware in the system is not capable of
- providing the 'this' pointer argument. You must use "normal" functions (non
- class members) or static member functions as interrupt service routines.
-
- One possible solution is to use a static member as the interrupt service
- routine and have that function look somewhere to find the instance/member pair
- that should be called on interrupt. Thus the effect is that a normal method
- is invoked on an interrupt, but for technical reasons you need to call an
- intermediate function first.
-
- ==============================================================================
-
- Q120: Why am I having trouble taking the address of a C++ function?
-
- This is a corollary to the previous FAQ.
-
- Long answer: In C++, member fns have an implicit parameter which points to the
- object (the "this" ptr inside the member fn). Normal C fns can be thought of
- as having a different calling convention from member fns, so the types of their
- ptrs (ptr-to-member-fn vs ptr-to-fn) are different and incompatible. C++
- introduces a new type of ptr, called a ptr-to-member, which can be invoked only
- by providing an object (see ARM ["Annotated Reference Manual"] 5.5).
-
- NOTE: do NOT attempt to "cast" a ptr-to-mem-fn into a ptr-to-fn; the result is
- undefined and probably disastrous. E.g., a ptr-to- member-fn is NOT required
- to contain the machine addr of the appropriate fn (see ARM, 8.1.2c, p.158). As
- was said in the last example, if you have a ptr to a regular C fn, use either a
- top-level (non-member) fn, or a "static" (class) member fn.
-
- ==============================================================================
-
- Q121: How do I declare an array of pointers to member functions?
-
- Keep your sanity with "typedef".
-
- class Fred {
- public:
- int f(char x, float y);
- int g(char x, float y);
- int h(char x, float y);
- int i(char x, float y);
- //...
- };
-
- typedef int (Fred::*FredPtr)(char x, float y);
-
- Here's the array of pointers to member functions:
-
- FredPtr a[4] = { &Fred::f, &Fred::g, &Fred::h, &Fred::i };
-
- To call one of the member functions on object "fred":
-
- void userCode(Fred& fred, int methodNum, char x, float y)
- {
- //assume "methodNum" is between 0 and 3 inclusive
- (fred.*a[methodNum])(x, y);
- }
-
- You can make the call somewhat clearer using a #define:
-
- #define callMethod(object,ptrToMethod) ((object).*(ptrToMethod))
- callMethod(fred, a[methodNum]) (x, y);
-
- ==============================================================================
- SECTION 19: Container classes and templates
- ==============================================================================
-
- Q122: How can I build a <favorite container> of objects of different types?
-
- You can't, but you can fake it pretty well. In C/C++ all arrays are
- homogeneous (i.e., the elements are all the same type). However, with an extra
- layer of indirection you can give the appearance of a heterogeneous container
- (a heterogeneous container is a container where the contained objects are of
- different types).
-
- There are two cases with heterogeneous containers.
-
- The first case occurs when all objects you want to store in a container are
- publically derived from a common base class. You can then declare/define your
- container to hold pointers to the base class. You indirectly store a derived
- class object in a container by storing the object's address as an element in
- the container. You can then access objects in the container indirectly through
- the pointers (enjoying polymorphic behavior). If you need to know the exact
- type of the object in the container you can use 'dynamic_cast<>' or 'typeid()'.
- You'll probably need the virtual constructor (a.k.a. cloning) idiom to copy a
- container of disparate object types. The downside of this approach is that it
- makes memory management a little more problematic (who "owns" the pointed-to
- objects? if you 'delete' these pointed-to objects when you destroy the
- container, how can you guarantee that no one else has a copy of one of these
- pointers? if you don't 'delete' these pointed-to objects when you destroy the
- container, how can you be sure that someone else will eventually do the
- 'delete'ing?). It also makes copying the container more complex (may actually
- break the container's copying functions since you don't want to copy the
- pointers, at least not when the container "owns" the pointed-to objects).
-
- The second case occurs when the object types are disjoint -- they do not share
- a common base class. The approach here is to use a handle class. The
- container is a container of handle objects (by value or by pointer, your
- choice; by value is easier). Each handle object knows how to "hold on to"
- (i.e. ,maintain a pointer to) one of the objects you want to put in the
- container. You can use either a single handle class with several different
- types of pointers as instance data, or a hierarchy of handle classes that
- shadow the various types you wish to contain (requires the container be of
- handle base clsss pointers). The downside of this approach is that it opens up
- the handle class(es) to maintenance every time you change the set of types that
- can be contained. The benefit is that you can use the handle class(es) to
- encapsulate most of the ugliness of memory management and object lifetime.
- Thus using handle objects may be beneficial even in the first case.
-
- [Adapted with permission from an email from Phil Staite, pstaite@vnet.ibm.com].
-
- ==============================================================================
-
- Q123: How can I insert/access/change elements from a linked
- list/hashtable/etc?
-
- I'll use an "inserting into a linked list" as a prototypical example. It's easy
- to allow insertion at the head and tail of the list, but limiting ourselves to
- these would produce a library that is too weak (a weak library is almost worse
- than no library).
-
- This answer will be a lot to swallow for novice C++'ers, so I'll give a couple
- of options. The first option is easiest; the second and third are better.
-
- [1] Empower the "List" with a "current location," and methods such as
- advance(), backup(), atEnd(), atBegin(), getCurrElem(), setCurrElem(Elem),
- insertElem(Elem), and removeElem(). Although this works in small examples, the
- notion of "a" current position makes it difficult to access elements at two or
- more positions within the List (e.g., "for all pairs x,y do the following...").
-
- [2] Remove the above methods from the List itself, and move them to a separate
- class, "ListPosition." ListPosition would act as a "current position" within a
- List. This allows multiple positions within the same List. ListPosition would
- be a friend of List, so List can hide its innards from the outside world (else
- the innards of List would have to be publicized via public methods in List).
- Note: ListPosition can use operator overloading for things like advance() and
- backup(), since operator overloading is syntactic sugar for normal methods.
-
- [3] Consider the entire iteration as an atomic event, and create a class
- template to embodies this event. This enhances performance by allowing the
- public access methods (which may be virtual fns) to be avoided during the inner
- loop. Unfortunately you get extra object code in the application, since
- templates gain speed by duplicating code. For more, see [Koenig, "Templates as
- interfaces," JOOP, 4, 5 (Sept 91)], and [Stroustrup, "The C++ Programming
- Language Second Edition," under "Comparator"].
-
- ==============================================================================
-
- Q124: What's the idea behind "templates"?
-
- A template is a cookie-cutter that specifies how to cut cookies that all look
- pretty much the same (although the cookies can be made of various kinds of
- dough, they'll all have the same basic shape). In the same way, a class
- template is a cookie cutter to description of how to build a family of classes
- that all look basically the same, and a function template describes how to
- build a family of similar looking functions.
-
- Class templates are often used to build type safe containers (although this
- only scratches the surface for how they can be used).
-
- ==============================================================================
-
- Q125: What's the syntax / semantics for a "function template"?
-
- Consider this function that swaps its two integer arguments:
-
- void swap(int& x, int& y)
- {
- int tmp = x;
- x = y;
- y = tmp;
- }
-
- If we also had to swap floats, longs, Strings, Sets, and FileSystems, we'd get
- pretty tired of coding lines that look almost identical except for the type.
- Mindless repetition is an ideal job for a computer, hence a function template:
-
- template<class T>
- void swap(T& x, T& y)
- {
- T tmp = x;
- x = y;
- y = tmp;
- }
-
- Every time we used "swap()" with a given pair of types, the compiler will go to
- the above definition and will create yet another "template function" as an
- instantiation of the above. E.g.,
-
- main()
- {
- int i,j; /*...*/ swap(i,j); //instantiates a swap for "int"
- float a,b; /*...*/ swap(a,b); //instantiates a swap for "float"
- char c,d; /*...*/ swap(c,d); //instantiates a swap for "char"
- String s,t; /*...*/ swap(s,t); //instantiates a swap for "String"
- }
-
- (note: a "template function" is the instantiation of a "function template").
-
- ==============================================================================
-
- Q126: What's the syntax / semantics for a "class template"?
-
- Consider a container class of that acts like an array of integers:
-
- //this would go into a header file such as "Array.h"
- class Array {
- public:
- Array(int len=10) : len_(len), data_(new int[len]){}
- ~Array() { delete [] data_; }
- int len() const { return len_; }
- const int& operator[](int i) const { data_[check(i)]; }
- int& operator[](int i) { data_[check(i)]; }
- Array(const Array&);
- Array& operator= (const Array&);
- private:
- int len_;
- int* data_;
- int check(int i) const
- { if (i < 0 || i >= len_) throw BoundsViol("Array", i, len_);
- return i; }
- };
-
- Just as with "swap()" above, repeating the above over and over for Array of
- float, of char, of String, of Array-of-String, etc, will become tedious.
-
- //this would go into a header file such as "Array.h"
- template<class T>
- class Array {
- public:
- Array(int len=10) : len_(len), data_(new T[len]) { }
- ~Array() { delete [] data_; }
- int len() const { return len_; }
- const T& operator[](int i) const { data_[check(i)]; }
- T& operator[](int i) { data_[check(i)]; }
- Array(const Array<T>&);
- Array& operator= (const Array<T>&);
- private:
- int len_;
- T* data_;
- int check(int i) const
- { if (i < 0 || i >= len_) throw BoundsViol("Array", i, len_);
- return i; }
- };
-
- Unlike template functions, template classes (instantiations of class templates)
- need to be explicit about the parameters over which they are instantiating:
-
- main()
- {
- Array<int> ai;
- Array<float> af;
- Array<char*> ac;
- Array<String> as;
- Array< Array<int> > aai;
- } // ^^^-- note the space; do NOT use "Array<Array<int>>"
- // (the compiler sees ">>" as a single token).
-
- ==============================================================================
-
- Q127: What is a "parameterized type"?
-
- Another way to say, "class templates."
-
- A parameterized type is a type that is parameterized over another type or some
- value. List<int> is a type ("List") parameterized over another type ("int").
-
- ==============================================================================
-
- Q128: What is "genericity"?
-
- Yet another way to say, "class templates."
-
- Not to be confused with "generality" (which just means avoiding solutions which
- are overly specific), "genericity" means class templates.
-
- ==============================================================================
- SECTION 20: Libraries
- ==============================================================================
-
- Q129: Where can I get a copy of "STL"?
-
- "STL" is the "Standard Templates Library". You can get a copy from:
-
- An STL site:
- ftp://ftp.cs.rpi.edu/pub/stl
-
- STL HP official site:
- ftp://butler.hpl.hp.com/stl
-
- STL code alternate:
- ftp://ftp.cs.rpi.edu/stl
-
- STL code + examples:
- http://www.cs.rpi.edu/~musser/stl.html
-
- STL hacks for GCC-2.6.3 are part of the GNU libg++ package 2.6.2.1 or later
- (and they may be in an earlier version as well). Thanks to Mike Lindner.
-
- ==============================================================================
-
- Q130: Where can I ftp the code that accompanies "Numerical Recipes"?
-
- This software is sold and there for it would be illegal to provide it on the
- net. However, it's only about $30.
-
- ==============================================================================
-
- Q131: Why is my executable so large?
-
- Many people are surprised by how big executables are, especially if the source
- code is trivial. For example, a simple "hello world" program can generate an
- executable that is larger than most people expect (40+K bytes).
-
- One reason executables can be large is that portions of the C++ runtime
- library gets linked with your program. How much gets linked in depends on how
- much of it you are using, and on how the implementor split up the library into
- pieces. For example, the iostream library is quite large, and consists of
- numerous classes and virtual functions. Using any part of it might pull in
- nearly all of the iostream code as a result of the interdependencies.
-
- You might be able to make your program smaller by using a dynamically-linked
- version of the library instead of the static version.
-
- You have to consult your compiler manuals or the vendor's technical support
- for a more detailed answer.
-
- ==============================================================================
- SECTION 21: Nuances of particular implementations
- ==============================================================================
-
- Q132: GNU C++ (g++) produces big executables for tiny programs; Why?
-
- libg++ (the library used by g++) was probably compiled with debug info (-g).
- On some machines, recompiling libg++ without debugging can save lots of disk
- space (~1 Meg; the down-side: you'll be unable to trace into libg++ calls).
- Merely "strip"ping the executable doesn't reclaim as much as recompiling
- without -g followed by subsequent "strip"ping the resultant "a.out"s.
-
- Use "size a.out" to see how big the program code and data segments really are,
- rather than "ls -s a.out" which includes the symbol table.
-
- ==============================================================================
-
- Q133: Is there a yacc-able C++ grammar?
-
- Jim Roskind is the author of a yacc grammar for C++. It's roughly compatible
- with the portion of the language implemented by USL cfront 2.0 (no templates,
- no exceptions, no run-time-type-identification). Jim's grammar deviates from
- C++ in a couple of minor-but-subtle ways.
-
- The grammar can be accessed on-line as follows:
- * ftp://ics.uci.edu/gnu/c++grammar2.0.tar.Z
- (ics.uci.edu is IP 128.195.1.1)
- * ftp://mach1.npac.syr.edu/pub/C++/c++grammar2.0.tar.Z
- (mach1.npac.syr.edu is IP 128.230.7.14)
-
- [NOTE: I was told that these ftp addresses are no longer valid. Would someone
- please either confirm or deny this assertion, and would someone please let me
- know of an alternate address. Thanks; Marshall Cline]
-
- ==============================================================================
-
- Q134: What is C++ 1.2? 2.0? 2.1? 3.0?
-
- These are not versions of the language, but rather versions of cfront, which
- was the original C++ translator implemented by AT&T. It has become generally
- accepted to use these version numbers as if they were versions of the language
- itself.
-
- *VERY* roughly speaking, these are the major features:
- * 2.0 includes multiple/virtual inheritance and pure virtual functions.
- * 2.1 includes semi-nested classes and "delete [] ptr_to_array."
- * 3.0 includes fully-nested classes, templates and "i++" vs "++i."
- * 4.0 will include exceptions.
-
- ==============================================================================
-
- Q135: If name mangling was standardized, could I link code compiled with
- compilers from different compiler vendors?
-
- Short answer: Probably not.
-
- In other words, some people would like to see name mangling standards
- incorporated into the proposed C++ ANSI standards in an attempt to avoiding
- having to purchase different versions of class libraries for different
- compiler vendors. However name mangling differences are one of the smallest
- differences between implementations, even on the same platform. Here is a
- partial list of other differences:
-
- 1) Number and type of hidden arguments to member functions.
- 1a) is 'this' handled specially?
- 1b) where is the return-by-value pointer passed?
- 2) Assuming a vtable is used:
- 2a) what is its contents and layout?
- 2b) where/how is the adjustment to 'this' made for multiple inheritance?
- 3) How are classes laid out, including:
- 3a) location of base classes?
- 3b) handling of virtual base classes?
- 3c) location of vtable pointers, if vtables are used?
- 4) Calling convention for functions, including:
- 4a) does caller or callee adjust the stack?
- 4b) where are the actual parameters placed?
- 4c) in what order are the actual parameters passed?
- 4d) how are registers saved?
- 4e) where does the return value go?
- 4f) special rules for passing or returning structs or doubles?
- 4g) special rules for saving registers when calling leaf functions?
- 5) How is the run-time-type-identification laid out?
- 6) How does the runtime exception handling system know which local objects
- need to be destructed during an exception throw?
-
- ==============================================================================
- SECTION 22: Miscellaneous technical and environmental issues
- ==============================================================================
- SUBSECTION 22A: Miscellaneous technical issues:
- ==============================================================================
-
- Q136: Why are classes with static data members getting linker errors?
-
- Static data members must be explicitly defined in exactly one module. E.g.,
-
- class Fred {
- public:
- //...
- private:
- static int i_; //declares static data member "Fred::i_"
- //...
- };
-
- The linker will holler at you ("Fred::i_ is not defined") unless you define (as
- opposed to declare) "Fred::i_" in (exactly) one of your source files:
-
- int Fred::i_ = some_expression_evaluating_to_an_int;
- or:
- int Fred::i_;
-
- The usual place to define static data members of class "Fred" is file "Fred.C"
- (or "Fred.cpp", etc; whatever filename extension you use).
-
- ==============================================================================
-
- Q137: What's the difference between the keywords struct and class?
-
- The members and base classes of a struct are public by default, while in class,
- they default to private. Note: you should make your base classes EXPLICITLY
- public, private, or protected, rather than relying on the defaults.
-
- "struct" and "class" are otherwise functionally equivalent.
-
- ==============================================================================
-
- Q138: Why can't I overload a function by its return type?
-
- If you declare both "char f()" and "float f()", the compiler gives you an error
- message, since calling simply "f()" would be ambiguous.
-
- ==============================================================================
-
- Q139: What is "persistence"? What is a "persistent object"?
-
- A persistent object can live after the program which created it has stopped.
- Persistent objects can even outlive different versions of the creating program,
- can outlive the disk system, the operating system, or even the hardware on
- which the OS was running when they were created.
-
- The challenge with persistent objects is to effectively store their method code
- out on secondary storage along with their data bits (and the data bits and
- method code of all member objects, and of all their member objects and base
- classes, etc). This is non-trivial when you have to do it yourself. In C++,
- you have to do it yourself. C++/OO databases can help hide the mechanism for
- all this.
-
- ==============================================================================
-
- Q140: Why is floating point so inaccurate? Why doesn't this print 0.43?
-
- #include<iostream.h>
-
- main()
- {
- float a = 1000.43;
- float b = 1000.0;
- cout << a - b << '\n';
- }
-
- (note, on one C++ implementation, this prints 0.429993)
-
- Disclaimer: Frustration with rounding/truncation/approximation isn't really a
- C++ issue. It's a computer science issue. However, people keep asking about
- it on comp.lang.c++, so here's a nominal answer.
-
- Answer: Floating point is an approximation. The IEEE standard for 32 bit
- float supports 1 bit of sign, 8 bits of exponent, and 23 bits of mantissa.
- Since a normalized binary-point mantissa always has the form 1.xxxxx... the
- leading 1 is dropped and you get effectively 24 bits of mantissa. The number
- 1000.43 (and many, many others) is not exactly representable in float or
- double format. 1000.43 is actually represented as the following bitpattern
- (the 's' shows the position of the sign bit, the 'e's show the positions of
- the exponent bits, and the 'm's show the positions of the mantissa bits):
-
- seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
- 01000100011110100001101110000101
-
- The shifted mantissa is 1111101000.01101110000101 or 1000 + 7045/16384. The
- fractional part is 0.429992675781. With 24 bits of mantissa you only get
- about 1 part in 16M of precision for float. The 'double' type provides more
- precision (53 bits of mantissa).
-
- ==============================================================================
- SUBSECTION 22B: Miscellaneous environmental issues:
- ==============================================================================
-
- Q141: Is there a TeX or LaTeX macro that fixes the spacing on "C++"?
-
- Yes, here are three (the first prevents line breaks between the "C" and "++"):
-
- \def\CC{{C\nolinebreak[4]\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}}
-
- \def\CC{C\raise.22ex\hbox{{\footnotesize +}}\raise.22ex\hbox{\footnotesize +}}
-
- \def\CC{{C\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}}
-
- ==============================================================================
-
- Q142: Where can I access C++2LaTeX, a LaTeX pretty printer for C++ source?
-
- ftp://ftp.german.eu.net/pub/packages/TeX/support/pretty/C++2LaTeX-3.02.tar.gz
-
- ==============================================================================
-
- Q143: Where can I access "tgrind," a pretty printer for C++/C/etc source?
-
- "tgrind" reads a C++ source file, and spits out something that looks pretty on
- most Unix printers. It usually comes with the public distribution of TeX and
- LaTeX; look in the directory: "...tex82/contrib/van/tgrind". A more up-to-date
- version of tgrind by Jerry Leichter can be found on: venus.ycc.yale.edu in
- [.TGRIND].
-
- ==============================================================================
-
- Q144: Is there a C++-mode for GNU emacs? If so, where can I get it?
-
- Yes, there is a C++-mode for GNU emacs.
-
- The latest and greatest version of C++-mode (and c-mode) is implemented in the
- file cc-mode.el. It is an extension of Detlef & Clamen's version.
- A version is included with emacs. Newer version are availiable from
- the elisp archives.
-
- ==============================================================================
-
- Q145: Where can I get OS-specific FAQs answered (e.g.,BC++,DOS,Windows,etc)?
-
- See one of the following:
- * comp.os.msdos.programmer
- * comp.windows.ms.programmer
- * comp.unix.programmer
-
- [If anyone has an email address for a BC++, VC++, or Semantic C++ bug list
- and/or discussion mailing list, please let me know how to subscribe, and I'll
- mention it here].
-
- ==============================================================================
-
- Q146: Why does my DOS C++ program says "Sorry: floating point code not
- linked"?
-
- The compiler attempts to save space in the executable by not including the
- float-to-string format conversion routines unless they are necessary, but
- sometimes it guesses wrong, and gives you the above error message. You can fix
- this by (1) using <iostream.h> instead of <stdio.h>, or (2) by including the
- following function somewhere in your compilation (but don't call it!):
-
- static void dummyfloat(float *x) { float y; dummyfloat(&y); }
-
- See FAQ on stream I/O for more reasons to use <iostream.h> vs <stdio.h>.
-
- ==============================================================================
-
- Q147: Why does my BC++ Windows app crash when I'm not running the BC45 IDE?
-
- If you're using BC++ for a Windows app, and it works ok as long as you have the
- BC45 IDE running, but when the BC45 IDE is shut down you get an exception
- during the creation of a window, then add the following line of code to the
- InitMainWindow() method of your application ("YourApp::InitMainWindow()"):
-
- EnableBWCC(TRUE);
-
- ==============================================================================
-
- --
- Paradigm Shift, Inc. / P.O. Box 5108 / Potsdam, NY 13676
- Technology consulting services
- cline@parashift.com / Voice: 315-353-6100 / FAX: 315-353-6110
-